---
title: Twoslash 查询
description: 查询 Twoslash 的用法和示例。
sidebar:
  order: 2
---

import { Tabs, TabItem } from '@astrojs/starlight/components';

`ArkTS for twoslash` 同样支持所有 `TypeScript Twoslash` 的查询语法，下面将展示一些简单的示例。

## Extract Types: 提取类型

您可以使用 `^?` 符号并结合 `//` 注释来提取类型：

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    struct Index {
      build() {
        Column() {

        }.width(100)
         // ^?
      }
    }

    @interface MyInterface {
      value: string
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    struct Index {
      build() {
        Column() {

        }.width(100)
         // ^?
      }
    }
    ```
  </TabItem>
</Tabs>

这样，您的类型将直接出现在代码块下方，而无需鼠标悬停（或移动端触摸）来查看类型。这对于展示文档的类型信息来说非常有用。

## Completions: 展示代码补全

您可以使用 `^|` 符号并结合 `//` 注释来展示代码补全：

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    // @noErrors
    struct Index {
      build() {
        Column() {

        }.b
        // ^|
      }
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    // @noErrors
    struct Index {
      build() {
        Column() {

        }.b
        // ^|
      }
    }
    ```
  </TabItem>
</Tabs>

在这里我们使用了 `// @noErrors` 注释来禁用错误提示，因为 `Column()` 组件尾随的 `.b` 是无效的属性，而且我们并不关心这个错误，因此只需要使用 `// @noErrors` 注释来禁用所有错误提示即可。

:::note

默认情况下，`Twoslash` 只展示 5 个补全项，详见 [Twoslash 文档](https://twoslash.netlify.app/refs/notations#completions)。

:::

## Highlighting: 高亮

您可以使用 `^^^` 符号并结合 `//` 注释来高亮特定范围的代码：

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    struct Index {
        // ^^^^^
      build() {
        Column() {

        }.width(100)
      }
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    struct Index {
        // ^^^^^
      build() {
        Column() {

        }.width(100)
      }
    }
    ```
  </TabItem>
</Tabs>

它取决于集成渲染器如何呈现这些信息。通常, `Shiki` 集成将它们包装在 `.twoslash-highlighted` 类中，而样式则由您自己的 `CSS` 样式文件来决定。

## Cutting: 裁剪代码

每个 `Twoslash` 代码示例实际上都是一个完整的 `ArkTS/TypeScript` 程序，所以它需要能够 `编译成功`。因此通常为了编译成功，通常会在 markdown 中撰写很多与用户无关的代码。这时，您可以使用下面的一些符号对渲染结果进行裁剪。

### `// ---cut-before---`

Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the // ---cut-before---. A shorthand // ---cut--- is also available.

这个注释会在 `TypeScript` 生成项目并提取所有编辑器信息（如标识符、查询、高亮等）后，调整所有偏移量和行数以便只渲染用户所关心的代码。用户看到的是 `// ---cut-before---` 之后的所有内容，也可以简写 `// ---cut---` 来达到效果。

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    import { ArcList, ArcListItem } from "@kit.ArkUI";

    // ---cut-before---
    struct Index {
      build() {
        Column() {
          ArcList() {
            ArcListItem() {
              Text("Item 1")
            }
          }
        }.width(100)
      }
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    import { ArcList, ArcListItem } from "@kit.ArkUI";

    // ---cut-before---
    struct Index {
      build() {
        Column() {
          ArcList() {
            ArcListItem() {
              Text("Item 1")
            }
          }
        }.width(100)
      }
    }
    ```
  </TabItem>
</Tabs>

您可以看到上方的 `import { ArcList, ArcListItem } from "@kit.ArkUI";` 代码被裁剪掉了，只保留了下方的 `struct Index { ... }` 代码。

### 多文件支持

当你想展示一个多文件的代码段的时候，可以使用 `@filename` 注释来指定文件名。

结合 `// ---cut-before---` 注释，可以裁剪掉不需要展示的文件内容。

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash frame="none"
    // @filename: foo.ets
    /**
     * 我的 Foo 组件
     */
    @Entry
    @Component
    export struct Foo {}
    // @filename: index.ets
    // ---cut-before---
    import { Foo } from './foo'

    @Entry
    @Component
    struct Index {
      build() {
        Foo()
      }
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets frame="none"
    // @filename: foo.ets
    /**
     * 我的 Foo 组件
     */
    @Entry
    @Component
    export struct Foo {}
    // @filename: index.ets
    // ---cut-before---
    import { Foo } from './foo'

    @Entry
    @Component
    struct Index {
      build() {
        Foo()
      }
    }
    ```
  </TabItem>
</Tabs>

### `// ---cut-after---`: 裁剪后面的代码

这个注释和 `// ---cut-before---` 注释相反，它会保留前面的代码。

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    import { ArcList, ArcListItem } from '@kit.ArkUI'
    // ---cut-after---
    
    struct Index {
      build() {
        Column() {
          ArcList() {
            ArcListItem() {
              Text("Item 1")
            }
          }
        }.width(100)
      }
    }
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    import { ArcList, ArcListItem } from '@kit.ArkUI'
    // ---cut-after---
    
    struct Index {
      build() {
        Column() {
          ArcList() {
            ArcListItem() {
              Text("Item 1")
            }
          }
        }.width(100)
      }
    }
    ```
  </TabItem>
</Tabs>

可以看到下方的 `struct Index { ... }` 代码被裁剪掉了，只保留了前面的 `import { ArcList, ArcListItem } from '@kit.ArkUI'` 代码。

### `// ---cut-start---` 和 `// ---cut-end---`: 只展示中间的代码

这两个注释和 `// ---cut-before---` 和 `// ---cut-after---` 注释的作用是相同的。

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    const level: string = 'Danger'
    // ---cut-start---
    console.log(level) // This is not shown.
    // ---cut-end---
    console.log('This is shown')
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    const level: string = 'Danger'
    // ---cut-start---
    console.log(level) // This is not shown.
    // ---cut-end---
    console.log('This is shown')
    ```
  </TabItem>
</Tabs>

## 重写编译器选项

您可以使用 `// @name` 和 `// @name: value` 注释来重写 `TypeScript` 语言特性和 [Twoslash手册选项](https://twoslash.netlify.app/refs/options#handbook-options)。这些注释将被从输出中移除。

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    // @noImplicitAny: false
    // @target: esnext
    // @lib: esnext
    // This suppose to throw an error,
    // but it won't because we disabled noImplicitAny.
    const fn = a => a + 1
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    // @noImplicitAny: false
    // @target: esnext
    // @lib: esnext
    // This suppose to throw an error,
    // but it won't because we disabled noImplicitAny.
    const fn = a => a + 1
    ```
  </TabItem>
</Tabs>

## 展示代码编译输出

`twoslash` 允许直接展示编译后的代码，只需要使用 `@showEmit` 注释即可。但是，目前 `@showEmit` 注释在 `ArkTS` 中会报错，因此建议请仅展示 `.d.ets` 声明文件，因此请在使用 `@showEmit` 注释时，同时使用 `@declaration` 和 `@emitDeclarationOnly` 注释来展示声明文件。

### `@showEmit`

在 `ArkTS` 中展示编译后的代码是不现实的，因为 `ArkTS` 代码将会编译为 `.abc` 字节码，展示由 `ohos-typescript` 编译后的代码意义不大。而且现在貌似 `ohos-typescript` 貌似无法输出包含 `struct` 声明的编译后的 `.js` 代码。当然，如果有大佬解决了这个问题，欢迎提交 `PR` 来更新这块儿的文档 ✨。

因此，退而求其次，我们在使用了 `@showEmit` 注释时默认会展示 `.d.ets` 声明文件的代码：

<Tabs>
  <TabItem label="Twoslash 渲染后">
    ```ets twoslash
    // @showEmit
    @Entry
    @Component
    export struct Index {
      build() {
        Column() {
          Text('Hello, world!')
        }.width(100)
      }
    }

    // 在 ohos-typescript@4.9.5-r10 中，@interface 装饰器已经支持了，但是貌似仍然无法展示装饰器的类型信息
    @interface MyDecorator {
      value: string
    }

    @MyDecorator({ value: 'Hello, world!' })
    class MyClass {}
    ```
  </TabItem>
  <TabItem label="Markdown 源代码">
    ```ets
    // @showEmit
    @Entry
    @Component
    export struct Index {
      build() {
        Column() {
          Text('Hello, world!')
        }.width(100)
      }
    }

    // 在 ohos-typescript@4.9.5-r10 中，@interface 装饰器已经支持了，但是貌似仍然无法展示装饰器的类型信息
    @interface MyDecorator {
      value: string
    }

    @MyDecorator({ value: 'Hello, world!' })
    class MyClass {}
    ```
  </TabItem>
</Tabs>